﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;

namespace SurveyListsAdministration
{
    public static class SPTools
    {
        public static void CheckSurveyItem(SPItemEventProperties properties)
        {
            using (SPSite site = new SPSite(properties.SiteId))
            {
                using (SPWeb rootWeb = site.RootWeb)
                {
                    SPList administrationList = GetSurveyAdministrationList(rootWeb);
                    SPListItem surveyAdministrationItem = GetSurveyAdministrationItem(administrationList, properties.ListItem);
                    bool surveyAdministrationItemExists = (surveyAdministrationItem != null);
                    if (!properties.ListItem.HasPublishedVersion && !surveyAdministrationItemExists)
                    {
                        AddSurveyAdministrationItem(administrationList, properties.ListItem);
                    }
                    else if (properties.ListItem.HasPublishedVersion && surveyAdministrationItemExists)
                    {
                        surveyAdministrationItem.Delete();
                    }
                }
            }
        }

        public static SPList GetSurveyAdministrationList(SPWeb rootWeb)
        {
            string listUrl = SPUrlUtility.CombineUrl(rootWeb.ServerRelativeUrl, SPData.Lists.SurveyAdministrationList.WEB_RELATIVE_URL);
            SPList administrationList = rootWeb.GetList(listUrl);
            return administrationList;
        }

        public static SPList GetSurveyAdministrationList(SPFeatureReceiverProperties properties)
        {
            SPSite site = properties.Feature.Parent as SPSite;
            return GetSurveyAdministrationList(site.RootWeb);
        }

        public static SPListItem GetSurveyAdministrationItem(SPList administrationList, SPListItem listItem)
        {
            SPQuery query = new SPQuery();
            string camlQuery = GetSurveyAdministrationQueryByID(listItem.ID, listItem.ParentList.ID, listItem.Web.ID);
            query.Query = camlQuery;

            SPListItemCollection items = administrationList.GetItems(query);

            if (items.Count > 1)
            {
                throw new SPException("There is a problem with the survey administration list.");
            }
            else if (items.Count == 0)
            {
                return null;
            }
            else
            {
                return items[0];
            }
        }

        public static void AddSurveyAdministrationItem(SPList administrationList, SPListItem listItem)
        {
            SPListItem surveyAdministrationItem = administrationList.AddItem();
            SPWeb surveyWeb = listItem.Web;
            SPList surveyList = listItem.ParentList;
            string listFullUrl = SPUrlUtility.CombineUrl(surveyWeb.Url, surveyList.RootFolder.Url);

            SetFieldUrl(surveyAdministrationItem, listFullUrl, surveyWeb.Title, SPData.Lists.SurveyAdministrationList.Fields.LIST);
            SetFieldUrl(surveyAdministrationItem, surveyWeb.Url, surveyWeb.Title, SPData.Lists.SurveyAdministrationList.Fields.WEB);
            SetField(surveyAdministrationItem, listItem.ID, SPData.Lists.SurveyAdministrationList.Fields.ITEM_ID);
            SetFieldGuid(surveyAdministrationItem, surveyWeb.ID, SPData.Lists.SurveyAdministrationList.Fields.WEB_ID);
            SetFieldGuid(surveyAdministrationItem, surveyList.ID, SPData.Lists.SurveyAdministrationList.Fields.LIST_ID);
            SetField(surveyAdministrationItem, listItem.DisplayName, SPData.Lists.SurveyAdministrationList.Fields.TITLE);
            SetField(surveyAdministrationItem, GetFieldValueAsUser(listItem, SPBuiltInFieldId.Author),
                                                                    SPData.Lists.SurveyAdministrationList.Fields.USER);
            surveyAdministrationItem.Update();
        }

        public static void DeleteSurveyItem(SPItemEventProperties properties)
        {
            SPListItem surveyAdministrationItem = properties.ListItem;

            SPFieldUserValue userValue = GetFieldValueAsUser(surveyAdministrationItem, SPData.Lists.SurveyAdministrationList.Fields.USER);
            SPUserToken userToken = userValue.User.UserToken;
            SPFieldUrlValue webUrlValue = GetFieldValueAsUrl(surveyAdministrationItem, SPData.Lists.SurveyAdministrationList.Fields.WEB);
            Guid listID = GetFieldValueAsGuid(surveyAdministrationItem, SPData.Lists.SurveyAdministrationList.Fields.LIST_ID);
            int responseId = GetFieldValueAsInt(surveyAdministrationItem, SPData.Lists.SurveyAdministrationList.Fields.ITEM_ID);

            using (SPSite site = new SPSite(webUrlValue.Url, userToken))
            {
                using (SPWeb userWeb = site.OpenWeb())
                {
                    try
                    {
                        userWeb.Lists[listID].GetItemById(responseId).Recycle();
                    }
                    catch (ArgumentException)
                    {
                        //Si l'item n'existe pas on ne fait rien.
                    }
                }
            }
        }

        public static void DeleteSurveyAdministrationItem(SPItemEventProperties properties)
        {
            using (SPSite site = new SPSite(properties.SiteId))
            {
                using (SPWeb rootWeb = site.RootWeb)
                {
                    SPList administrationList = GetSurveyAdministrationList(rootWeb);
                    SPListItem administrationItem = GetSurveyAdministrationItem(administrationList, properties.ListItem);
                    if (administrationItem != null)
                    {
                        administrationItem.Delete();
                    }
                }
            }
        }

        public static SPFieldUserValue GetFieldValueAsUser(SPListItem item, Guid fieldId)
        {
            SPFieldUserValue userFieldValue = new SPFieldUserValue(item.Web, item[fieldId].ToString());
            return userFieldValue;
        }

        public static SPFieldUserValue GetFieldValueAsUser(SPListItem item, string fieldInternalName)
        {
            SPField userField = GetField(item, fieldInternalName);
            return GetFieldValueAsUser(item, userField.Id);
        }

        public static int GetFieldValueAsInt(SPListItem item, string fieldInternalName)
        {
            SPField itemIdField = GetField(item, fieldInternalName);
            int itemId = Convert.ToInt32(item[itemIdField.Id]);
            return itemId;
        }

        public static Guid GetFieldValueAsGuid(SPListItem item, string fieldInternalName)
        {
            SPField field = GetField(item, fieldInternalName);
            Guid id = new Guid(item[field.Id].ToString());
            return id;
        }

        public static SPFieldUrlValue GetFieldValueAsUrl(SPListItem item, string fieldInternalName)
        {
            SPField field = GetField(item, fieldInternalName);
            SPFieldUrlValue fieldValue = (field.GetFieldValue(item[field.Id].ToString())) as SPFieldUrlValue;
            return fieldValue;
        }

        public static SPField GetField(SPListItem item, string fieldInternalName)
        {
            return item.Fields.GetFieldByInternalName(fieldInternalName);
        }

        public static string GetSurveyAdministrationQueryByID(int itemID, Guid listID, Guid webID)
        {
            StringBuilder camlBuilder = new StringBuilder();
            camlBuilder.Append("<Where>");
            camlBuilder.Append("<And>");
            camlBuilder.Append("<Eq>");
            camlBuilder.AppendFormat("<FieldRef Name='{0}' />", SPData.Lists.SurveyAdministrationList.Fields.ITEM_ID);
            camlBuilder.AppendFormat("<Value Type='Text'>{0}</Value>", itemID.ToString());
            camlBuilder.Append("</Eq>");
            camlBuilder.Append("<And>");
            camlBuilder.Append("<Eq>");
            camlBuilder.AppendFormat("<FieldRef Name='{0}'/>", SPData.Lists.SurveyAdministrationList.Fields.LIST_ID);
            camlBuilder.AppendFormat("<Value Type='Text'>{0}</Value>", listID.ToStringWithBraces());
            camlBuilder.Append("</Eq>");
            camlBuilder.Append("<Eq>");
            camlBuilder.AppendFormat("<FieldRef Name='{0}'/>", SPData.Lists.SurveyAdministrationList.Fields.WEB_ID);
            camlBuilder.AppendFormat("<Value Type='Text'>{0}</Value>", webID.ToStringWithBraces());
            camlBuilder.Append("</Eq>");
            camlBuilder.Append("</And>");
            camlBuilder.Append("</And>");
            camlBuilder.Append("</Where>");
            return camlBuilder.ToString();
        }

        public static void SetFieldUrl(SPListItem item, string url, string description, string fieldInternalName)
        {
            SPFieldUrlValue value = new SPFieldUrlValue();
            value.Description = description;
            value.Url = url;

            SetField(item, value, fieldInternalName);
        }

        private static void SetFieldGuid(SPListItem surveyAdministrationItem, Guid guid, string fieldInternalName)
        {
            string guidString = guid.ToStringWithBraces();
            SetField(surveyAdministrationItem, guidString, fieldInternalName);
        }

        public static void SetField(SPListItem item, object value, string fieldInternalName)
        {
            SPField field = GetField(item, fieldInternalName);
            item[field.Id] = value;
        }

        public static void AddEventReceiverToSurveyAdministrationList(SPFeatureReceiverProperties properties)
        {
            SPList surveyAdminList = GetSurveyAdministrationList(properties);
            Type surveyAdminEventHandlerType = typeof(AdministrationListEventHandler);
            string assemblyFullName = surveyAdminEventHandlerType.Assembly.FullName;
            string classNamespace = surveyAdminEventHandlerType.Namespace;
            string className = surveyAdminEventHandlerType.Name;
            string fullClassName = string.Format("{0}.{1}", classNamespace, className);
            surveyAdminList.EventReceivers.Add(SPEventReceiverType.ItemDeleting, assemblyFullName, fullClassName);
        }

        public static void RemoveSurveyAdministrationList(SPFeatureReceiverProperties properties)
        {
            SPList surveyAdminList = GetSurveyAdministrationList(properties);
            surveyAdminList.Delete();
        }

        public static string GetLocalizedString(SPWeb web, string resourceKey)
        {
            string resourceFileName = "SurveyListAdministrationResources";
            string key = string.Format("$Resources:{0}", resourceKey);
            return SPUtility.GetLocalizedString(key, resourceFileName, Convert.ToUInt32(web.Locale.LCID));
        }

        public static SPSite GetHPSite(string url)
        {
            SPSite HPSite = null;
            using (SPSite site = new SPSite(url))
            {
                HPSite = new SPSite(url, GetSystemToken(site));
            }
            return HPSite;
        }

        public static SPUserToken GetSystemToken(SPSite site)
        {
            SPUserToken token = null;
            bool tempCADE = site.CatchAccessDeniedException;
            try
            {
                site.CatchAccessDeniedException = false;
                token = site.SystemAccount.UserToken;
            }
            catch (UnauthorizedAccessException)
            {
                SPSecurity.RunWithElevatedPrivileges(() =>
                {
                    using (SPSite elevSite = new SPSite(site.ID))
                        token = elevSite.SystemAccount.UserToken;
                });
            }
            finally
            {
                site.CatchAccessDeniedException = tempCADE;
            }
            return token;
        }


    }
}
